package win.tbs.gulimall.product.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import win.tbs.common.utils.PageUtils;
import win.tbs.common.utils.Query;

import win.tbs.gulimall.product.dao.CategoryDao;
import win.tbs.gulimall.product.entity.CategoryEntity;
import win.tbs.gulimall.product.service.CategoryBrandRelationService;
import win.tbs.gulimall.product.service.CategoryService;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {


    @Autowired
    CategoryBrandRelationService categoryBrandRelationService;


    @Override
    public List<CategoryEntity> listWithTree() {
        //1、查出所有分类
        List<CategoryEntity> entities = baseMapper.selectList(null);

        //方法1. 使用递归实现 (大多数时候能不用递归就别用,狂占内存还慢)
        //todo: 而且从结果看(对比结果的catId数目)演示代码的递归查询结果还是错的,但看了一会没看出错在哪
        //你看 递归理解困难,性能差劲,还容易出错
        List<CategoryEntity> menuFormatTreeWithRecursion =  menuFormatTreeWithRecursion(entities);

        //方法2. 使用map实现;3遍遍历就完事
        List<CategoryEntity> entities2 = baseMapper.selectList(null);
        List<CategoryEntity>  menuFormatTreeWithMap = menuFormatTreeWithMap(entities2);

        return menuFormatTreeWithMap;
    }


    private List<CategoryEntity>  menuFormatTreeWithMap(List<CategoryEntity> entities){
        Map<Long,CategoryEntity> all = new HashMap<>();

        //将虚拟根目录和所有目录放入map中
        CategoryEntity virtualRoot = new CategoryEntity();
        virtualRoot.setCatId(0L);
        all.put(virtualRoot.getCatId(),virtualRoot);
        for (CategoryEntity entity : entities) {
            all.put(entity.getCatId(), entity);
        }

        //遍历entities所有元素,将其放入父目录的child中
        for (CategoryEntity entity : entities) {
            CategoryEntity parentEntity = all.get(entity.getParentCid());
            if (parentEntity.getChildren()==null){
                parentEntity.setChildren(new ArrayList<>());
            }
            parentEntity.getChildren().add(entity);
        }

        //对all中所有元素的child进行排序
        for (CategoryEntity entity : all.values()) {
            if (entity.getChildren()!=null){
                entity.getChildren().sort((menu1,menu2)->{
                    //排序
                    return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort());
                });
            }
        }

        //返回根元素的所有child即可
        return all.get(0L).getChildren();
    }



    private List<CategoryEntity>  menuFormatTreeWithRecursion(List<CategoryEntity> entities){


        //2、组装成父子的树形结构
        List<CategoryEntity> level1Menus = entities.stream()
                //找到所有的一级分类
                .filter(categoryEntity ->
                        categoryEntity.getParentCid() == 0
                )
                //找到每个分类的子分类
                .map((menu)->{
                    menu.setChildren(getChildrens(menu,entities));
                    return menu;
                })
                //根据sort做排序处理
                .sorted((menu1,menu2)->{
                    return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort());
                })
                //收集为list
                .collect(Collectors.toList());

        return level1Menus;

    }

    //递归查找所有菜单的子菜单
    private List<CategoryEntity> getChildrens(CategoryEntity root,List<CategoryEntity> all){

        List<CategoryEntity> children = all.stream()
                //找到所有子分类
                .filter(categoryEntity -> {
                    return categoryEntity.getParentCid() == root.getCatId();
                })
                //对每个子分类寻找其子分类
                .map(categoryEntity -> {
                    //1、找到子菜单
                    categoryEntity.setChildren(getChildrens(categoryEntity,all));
                    return categoryEntity;
                })
                //做排序
                .sorted((menu1,menu2)->{
                    //2、菜单的排序
                    return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort());
                })
                //收集为list
                .collect(Collectors.toList());

        return children;
    }


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public void removeMenuByIds(List<Long> asList) {
        //TODO  1、检查当前删除的菜单，是否被别的地方引用

        //默认是物理删除,可以结合配置来进行逻辑删除
        baseMapper.deleteBatchIds(asList);
    }


    //[2,25,225]
    @Override
    public Long[] findCatelogPath(Long catelogId) {
        List<Long> paths = new ArrayList<>();
        List<Long> parentPath = findParentPath(catelogId, paths);

        Collections.reverse(parentPath);

        return parentPath.toArray(new Long[parentPath.size()]);
    }


    //225,25,2
    private List<Long> findParentPath(Long catelogId, List<Long> paths) {
        //1、收集当前节点id
        paths.add(catelogId);
        CategoryEntity byId = this.getById(catelogId);
        if (byId.getParentCid() != 0) {
            findParentPath(byId.getParentCid(), paths);
        }
        return paths;

    }

    @Override
    public void updateCascade(CategoryEntity category) {
        this.updateById(category);
        categoryBrandRelationService.updateCategory(category.getCatId(), category.getName());

        //同时修改缓存中的数据
        //redis.del("catalogJSON");等待下次主动查询进行更新
    }


}